public class MyBlockingQueue {
    private int[] items = new int[1000];
    private int head = 0;
    private int tail = 0;
    private int size = 0;

    public void put(int item) throws InterruptedException {
        synchronized(this){
            // 这里的if最好换成while
            // 否则 notifyAll 的时候, 该线程从 wait 中被唤醒,
            // 但是紧接着并未抢占到锁. 当锁被抢占的时候, 可能又已经队列满了
            // 就只能继续等待
            while (size == items.length){
                wait();
            }
            items[tail] = item;
            tail++;
            if(tail >= items.length){
                tail = 0;
            }
            size++;
            notify();
        }
    }

    public int take() throws InterruptedException {
        synchronized(this){
            while (size == 0){
                wait();
            }
            int ret = items[head];
            head++;
            if(head >= items.length){
                head = 0;
            }
            size--;
            notify();
            return ret;
        }
    }

    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue();
        Thread customer = new Thread(){
            @Override
            public void run() {
                while (true){
                    try {
                        System.out.println("消费了: " + queue.take());
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        customer.start();

        Thread producer = new Thread(){
            @Override
            public void run() {
                for (int i = 1; i <= 10000 ; i++) {
                    try {
                        queue.put(i);
                        System.out.println("生产了: " + i);
                        //Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        producer.start();

        try {
            customer.join();
            producer.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
